import 'package:json_annotation/json_annotation.dart';

part 'mcp_tool.g.dart';

/// MCP 工具参数定义
@JsonSerializable()
class McpToolParameter {
  final String name;
  final String type;
  final String? description;
  final bool required;
  final dynamic defaultValue;
  final List<String>? enumValues;

  McpToolParameter({
    required this.name,
    required this.type,
    this.description,
    this.required = false,
    this.defaultValue,
    this.enumValues,
  });

  factory McpToolParameter.fromJson(Map<String, dynamic> json) =>
      _$McpToolParameterFromJson(json);

  Map<String, dynamic> toJson() => _$McpToolParameterToJson(this);
}

/// MCP 工具定义
@JsonSerializable()
class McpTool {
  final String name;
  final String description;
  final List<McpToolParameter> parameters;
  final String? category;

  McpTool({
    required this.name,
    required this.description,
    required this.parameters,
    this.category,
  });

  factory McpTool.fromJson(Map<String, dynamic> json) =>
      _$McpToolFromJson(json);

  Map<String, dynamic> toJson() => _$McpToolToJson(this);

  /// 从 MCP 协议格式解析工具
  factory McpTool.fromMcpFormat(Map<String, dynamic> json) {
    final name = json['name'] as String;
    final description = json['description'] as String? ?? '';
    final inputSchema = json['inputSchema'] as Map<String, dynamic>?;

    final List<McpToolParameter> parameters = [];

    if (inputSchema != null) {
      final properties = inputSchema['properties'] as Map<String, dynamic>?;
      final required = inputSchema['required'] as List<dynamic>?;
      final requiredSet = required?.map((e) => e.toString()).toSet() ?? {};

      if (properties != null) {
        properties.forEach((key, value) {
          final prop = value as Map<String, dynamic>;
          parameters.add(
            McpToolParameter(
              name: key,
              type: prop['type'] as String? ?? 'string',
              description: prop['description'] as String?,
              required: requiredSet.contains(key),
              defaultValue: prop['default'],
              enumValues: (prop['enum'] as List<dynamic>?)
                  ?.map((e) => e.toString())
                  .toList(),
            ),
          );
        });
      }
    }

    return McpTool(
      name: name,
      description: description,
      parameters: parameters,
    );
  }
}

/// MCP 工具调用结果
@JsonSerializable()
class McpToolResult {
  final String toolName;
  final bool success;
  final dynamic result;
  final String? error;
  final DateTime timestamp;

  McpToolResult({
    required this.toolName,
    required this.success,
    this.result,
    this.error,
    DateTime? timestamp,
  }) : timestamp = timestamp ?? DateTime.now();

  factory McpToolResult.fromJson(Map<String, dynamic> json) =>
      _$McpToolResultFromJson(json);

  Map<String, dynamic> toJson() => _$McpToolResultToJson(this);
}

/// MCP 配置类型
enum McpConnectionType { cmd, sse }

/// MCP 配置
@JsonSerializable()
class McpConfig {
  final McpConnectionType type;
  final String? command;
  final List<String>? args;
  final Map<String, String>? env;
  final String? sseUrl;
  final Map<String, String>? headers;

  McpConfig({
    required this.type,
    this.command,
    this.args,
    this.env,
    this.sseUrl,
    this.headers,
  });

  factory McpConfig.fromJson(Map<String, dynamic> json) =>
      _$McpConfigFromJson(json);

  Map<String, dynamic> toJson() => _$McpConfigToJson(this);

  factory McpConfig.cmd({
    required String command,
    List<String>? args,
    Map<String, String>? env,
  }) {
    return McpConfig(
      type: McpConnectionType.cmd,
      command: command,
      args: args,
      env: env,
    );
  }

  factory McpConfig.sse({required String url, Map<String, String>? headers}) {
    return McpConfig(
      type: McpConnectionType.sse,
      sseUrl: url,
      headers: headers,
    );
  }
}
